/*
 * msgstat.c
 * 
 * Copyright 2012 Kamil Cukrowski <kamil@dyzio.pl>
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation version 2.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 * 
 */
#define MSGSTAT_VERSION "2.1.1"

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sysinfo.h>
#include <fcntl.h>
#include <syslog.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <arpa/inet.h>
#include <stdarg.h>

/* __HOSTNAME has first letter of the hostname in hex */

#ifndef __HOSTNAME
#erorr huj ci w dupe
#endif
#if __HOSTNAME == 'l'
#define LEONIDAS 1
#warning "compiling with leonidas"
#elif __HOSTNAME == 'u'
#define USTROPECET 1
#warning "compiling with ustropecet"
#elif __HOSTNAME == 'k'
#define KOMANDOS 1
#warning "compiling with komandos"
#endif

#ifndef LEONIDAS 
#include "../msgsrv/libs/msgserv.h"
#include "../msgsrv/libs/msgserv.c"
#else
#include <msgserv.h>
#endif
  
#if defined( LEONIDAS ) || defined( ROUTER )
#define CPUNUM 4
#elif defined( USTROPECET )
#define CPUNUM 2
#endif

#define MY_NAME "msgstat"
#define PINFO(smt, ...) do { printf(smt, ## __VA_ARGS__ ); printf("\n"); } while(0)
#define PDEBUG(str, ...) PDEBUGL(1, str, ##__VA_ARGS__);
#define PDEBUGL(x, str, ...) do{ if ( debug >= x ) _INTERNAL_LOGIT(str, ##__VA_ARGS__); }while(0)
#define PERROR(str, ...) do { printf(MY_NAME ": (%s:%s:%d): ", __FILE__,  __FUNCTION__,__LINE__); printf(str, ##__VA_ARGS__); printf("error %d:%s \n", errno, strerror(errno)); }while(0)
#define _INTERNAL_LOGIT(str, ...) do { printf( MY_NAME ": (%s:%s:%d): ", __FILE__, __FUNCTION__, __LINE__); printf(str, ##__VA_ARGS__); printf("\n"); }while(0)


struct cpu_use_type {
	int use, total;
};

struct net_use_type {
	unsigned long long rx;
	unsigned long long tx;
	char name[8];
};

struct disc_use_type {
	unsigned long rd_sectors;
	unsigned long wr_sectors;
};

in_addr_t server_ip = { 16777343 }; // 127.0.0.1
int PID;
int sockfd;
int refresh_time = 3;
int debug = 0;

struct net_use_type *g_net_use = NULL;
struct disc_use_type disc_use[2];

void safe_exit(int _w, void* pnt) 
{
	msglcd_disconnect(sockfd);
	free(g_net_use);
}
void sig_hup (int param) {
	PDEBUG("Signal received. Going down");
	exit(0);
}
#define fatal(format, ...) do { PERROR(format, ##__VA_ARGS__); exit(0); } while(0)

static int __attribute__((format (printf, 3, 4))) 
	mysnprintf (char *s, int n, const char *format, ...)
{
	/* its same as snprintf
	 * but does not write '\0' on the end of the string
	 * and returns number of chars *written*
	 * i dont even care about checking - be carefull */
	char msg[256];
	short int i;
	
	va_list va;
	va_start (va, format);
	vsnprintf (msg, sizeof(msg), format, va);
	msg[sizeof(msg) - 1] = 0;
	va_end (va);
	
	for (i=0; i < n && i < 256 && i < strlen(msg); ++i) {
		s[i] = msg[i];
	}
	return(i);
}

void parse_cmd(int argc, char *argv[])
{
	int c=0;
	opterr=0;
	while ( (c = getopt(argc, argv, "hdr:i:")) != -1 )
	switch (c) {
	case 'h':
		printf("MsgLCD: messaging system to LCD geteway.\n"
		"\t-h\tdisplay this help.\n"
		"\t-d\tdebug mode on (do not fork into the background);\n"
		"\t-r\tset refresh time in secends.\n"
		"\t-i<IP address>\t server ip address.\n");
		exit(0);
	case 'd':
		debug=1;
		break;
	case 'r':
		refresh_time=atoi(optarg);
		break;
	case 'i':
		server_ip=inet_addr(optarg);
		break;
	}
}

float get_temp (int number) 
{
	FILE *file_fd = NULL;
	char buff[8];
	
	/*
	 * hwmon2 -> number == {1,2,3} - motherboard tempn
	 * hwmon1 -> number == 4 - cpu temp
	 * hwmon0 -> number == 5 - gpu temp
	 */
	
	switch(number) {
		case 1:
			file_fd = fopen("/sys/devices/platform/it87.552/temp1_input","r");
			break;
		case 2:
			file_fd = fopen("/sys/devices/platform/it87.552/temp2_input","r");
			break;
		case 3:
			file_fd = fopen("/sys/devices/platform/it87.552/temp3_input","r");
			break;
		case 4:
			file_fd = fopen("/sys/devices/pci0000:00/0000:00:18.3/temp1_input","r");
			break;
		case 5:
			do { /* theres something cracked with my head */
				const char buff[3][75] = { 
					"/sys/devices/pci0000:00/0000:00:02.0/0000:01:00.0/hwmon/hwmon0/temp1_input" ,
					"/sys/devices/pci0000:00/0000:00:02.0/0000:01:00.0/hwmon/hwmon1/temp1_input" ,
					"/sys/devices/pci0000:00/0000:00:02.0/0000:01:00.0/hwmon/hwmon2/temp1_input" ,
				};
				file_fd = fopen(buff[0], "r");
				if ( !file_fd ) {
					file_fd = fopen(buff[1], "r");
					if ( !file_fd ) {
						file_fd = fopen(buff[2], "r");
					}
				}
			} while(0);
			break;
		default:
			file_fd = NULL;
	}
	if ( !file_fd ) {
		PDEBUG("error opening file: %d %s.", errno, strerror(errno));
		return -errno;
	}
	fgets(buff, 8, file_fd);
	fclose(file_fd);
	return ((float)atoi(buff)/(float)1000);
}

static void get_cpu_usage(float *cpuuse) 
{
	static struct cpu_use_type cpuuse_old[CPUNUM] = { [0 ... CPUNUM-1] = {0,0} };
	int i=0;
	char buff[256];
	FILE *stat_fd;
	
	struct {
		long int user, nice, sys, idle, iowait, hirq, sirq, use, hgw;
	} cpu_usage;
	
	if ( (stat_fd = fopen("/proc/stat","r")) == NULL ) {
		PDEBUG("/proc/stat err_fopen\n");
		return;
	}
	for (i=0; ( i<CPUNUM ) && ( fgets(buff,256,stat_fd) != NULL ) &&
		( sscanf(buff+5,"%ld %ld %ld %ld %ld %ld %ld %ld\n",
			&cpu_usage.user,
			&cpu_usage.nice,
			&cpu_usage.sys,
			&cpu_usage.idle,
			&cpu_usage.iowait,
			&cpu_usage.hirq,
			&cpu_usage.sirq,
			&cpu_usage.hgw) == 8 ) ; 
			i++ ) {
		const int use = cpu_usage.user+cpu_usage.nice+cpu_usage.sys+cpu_usage.hirq+cpu_usage.sirq;
		const int total = cpu_usage.idle+cpu_usage.iowait+cpu_usage.user+cpu_usage.nice+cpu_usage.sys+cpu_usage.hirq+cpu_usage.sirq;
		
		if ( total == cpuuse_old[i].total ) // avoid dividing throu zero
			cpuuse[i]=0;
		else
			cpuuse[i]=(float)((use-cpuuse_old[i].use)*100) / (float)( total-cpuuse_old[i].total);
		cpuuse_old[i].use=use;
		cpuuse_old[i].total=total;
	
	}
	fclose(stat_fd);
}

static char *strfindstr(char *str1, char *str2) 
{
	const int len2 = strlen(str2);
	const int len = strlen(str1) - len2;
	int i;
	
	for (i = 0; i < len; ++i)
            if ( !strncmp(str1 + i, str2, len2) )
		return str1+i;
	return NULL;

}

static int get_net_use(struct net_use_type *netuse, char *dev)
{
	char buff[1024];
	FILE *filefd;
	unsigned long int tmp;
	char *pnt;
	
	filefd = fopen("/proc/net/dev","r");
	if ( !filefd ) 
		goto err_fopen;
	
	while ( fgets(buff, 1024, filefd) )
		if ( ( pnt = strfindstr(buff, dev) ) )
			break;
	if ( feof(filefd) )
		goto err_dev_not_found;
	fclose(filefd);
	
	sscanf(pnt+strlen(dev)+1,
		"%llu %lu %lu %lu %lu %lu %lu %lu"
		"%llu %lu %lu %lu %lu %lu %lu %lu",
		&(*netuse).rx, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp,
		&(*netuse).tx, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp, &tmp);
	
	return 0;
	
err_dev_not_found:
	PDEBUG("err_dev_not_found \"%s\"", dev);
	(*netuse).rx = 9999;
	(*netuse).tx = -9999;
	fclose(filefd);
	return -1;
err_fopen:
	PDEBUG("err_fopep \"%s\"", dev);
	(*netuse).rx = 999999;
	(*netuse).tx = -999999;
	return -99999;
}

static int dynamic_get_net_use(struct net_use_type **_nu, int *_cnt)
{
	struct net_use_type *nu = *_nu;
	FILE *filefd;
	fpos_t fpos;
	int cnt, i;
	
	if ( !_nu || !_cnt )
		goto err_input;
	
	/* count the interfaces */
	filefd = fopen("/proc/net/dev","r");
	if ( !filefd ) goto err_fopen;
	
	/* omit two lines */
	if ( EOF == (fscanf(filefd, "%*[^\n]"), fscanf(filefd, "%*c") ) )
		goto err_fscanf;
	if ( EOF == (fscanf(filefd, "%*[^\n]"), fscanf(filefd, "%*c") ) )
		goto err_fscanf;
	
	fgetpos(filefd, &fpos);
	
	/* count the lines */
	cnt = -1; // omit lo interface
	while (EOF != (fscanf(filefd, "%*[^\n]"), fscanf(filefd, "%*c"))) 
		++cnt;
	
	fsetpos(filefd, &fpos);
	
	/* alloc memory */
	if ( *_cnt != cnt ) {
		*_nu = realloc(*_nu, sizeof(**_nu)*cnt*2);
		if ( *_nu == NULL )
			goto err_realloc;
		nu = *_nu;
	}
	
	for(i=0;i<cnt;i++) {
		struct net_use_type nu_tmp = {0, 0, ""};
		
		/* get info */
		fscanf(filefd,
			"%s"
			" %llu %*u %*u %*u %*u %*u %*u %*u"
			" %llu %*u %*u %*u %*u %*u %*u %*u",
			nu_tmp.name, &nu_tmp.tx, &nu_tmp.rx);
			
		if ( !strcmp(nu_tmp.name, "lo:") ) {
			i--;
			continue;
		}
		nu_tmp.name[strlen(nu_tmp.name)-1] = '\0';
		
		/* fill nu */		
		strncpy(nu[i].name, nu_tmp.name, 6);
		nu[i].name[7] = '\0';
		nu[i].rx = nu_tmp.rx - nu[i+cnt].rx;
		nu[i].tx = nu_tmp.tx - nu[i+cnt].tx;
		nu[i+cnt] = nu_tmp;
	}
	
	fclose(filefd);
	
	*_cnt = cnt;
	return 0;

err_realloc:
err_fopen:
err_fscanf:
err_input:
	return -99999;
}

static int get_disc_use(struct disc_use_type *nu)
{
	/* _nu[0] gets written with writed sectors and readed sectors in given refresh_time */
	const char filename[] = "/sys/block/sda/stat";
	struct disc_use_type nu_tmp;
	FILE *fp;
	
	/* Try to read given stat file */
	if ((fp = fopen(filename, "r")) == NULL)
		return -1;
	fscanf(fp, "%*u %*u %lu %*u %*u %*u %lu %*u %*u %*u %*u",
		&nu_tmp.rd_sectors, &nu_tmp.wr_sectors);
	fclose(fp);
	
	nu[0].rd_sectors = nu_tmp.rd_sectors - nu[1].rd_sectors;
	nu[0].wr_sectors = nu_tmp.wr_sectors - nu[1].wr_sectors;
	nu[1] = nu_tmp;
	
	return 0;
}

static void readable_net_size(char *buff, unsigned long long n, int len)
{
	n/=refresh_time;
	n*=8;
	
	//if ( len == 3 ) {
		
		if ( n < 1000 ) // 1 - 1024
			mysnprintf(buff, 4, "%3llub", n);
		else if ( n < 1024*1000 ) // 1 - 1024
			mysnprintf(buff, 4, "%3lluK", n/1024);
		else if ( n < 1024*1024*1000 )
			mysnprintf(buff, 4,"%3lluM", n/1024/1024);
		else if ( n < (unsigned long long)1024*1024*1025*1000 )
			mysnprintf(buff, 4, "%3lluG", n/1024/1024/1024);
		else if ( n < (unsigned long long)1024*1024*1024*1024*1000 )
			mysnprintf(buff, 4, "%3lluT", n/1024/1024/1024/1024);
		else if ( n < (unsigned long long)1024*1024*1024*1024*1024*1000 )
			mysnprintf(buff, 4, "%3llu?", n/1024/1024/1024/1024/1024);
		else
			mysnprintf(buff, 4, "%3llu?", n/1024/1024/1024/1024/1024/1024);
	return;
	
	//} else if ( len == 5 ) {
	
		if ( n < 1024 ) // 1 - 1024
			mysnprintf(buff, 5, "%4llub", n);
		else if ( n < 1024*10 ) // 1K - 10K
			mysnprintf(buff, 5, "%1.2fK", (float)n / (float)1024);
		else if ( n < 1024*100 ) // 10K - 100K                                                                                  
			mysnprintf(buff, 5, "%2.1fK", (float)n / (float)1024);
		else if ( n < 1024*1000 ) // 100K - 1024K                                                                               
			mysnprintf(buff, 5, "%4lluK", n / 1024);                                                                        
		else if ( n < 1024*1024 ) // 1M - 10M                                                                                  
			mysnprintf(buff, 5, "%1.2fM", (float)n / (float)1048576);
		else if ( n < 1024*1024*10 ) // 10M - 100M , 1048576 = 1024^2
			mysnprintf(buff, 5, "%2.1fM", (float)n / (float)1048576);
		else if ( n < 1024*1024*100 ) // 100M - 1024M , 1073741824 = 1024^3
			mysnprintf(buff, 5, "%4lluM", n/1048576 );
		else if ( n < 1024*1024*1024 ) // 1G - 1024G
			mysnprintf(buff, 5, "%4lluGb", (((n/1024)/1024)/1024) );
		else if ( n/1024 < 1024*1024*1024 )
			mysnprintf(buff, 5, "%4lluTb", (((n/1024)/1024)/1024)/1024 );
		else
			mysnprintf(buff, 5, "%4lluPb", (((n/1024)/1024)/1024)/(1024*1024) );
	//}
}

static void readable_cpu_usage(char *where, float n) 
{
	if ( n < 10 )
		mysnprintf(where, 3, "%1.1f", n);
	else 
		mysnprintf(where, 3, "%3.0f", n);
}

static void readable_mem_size(char *buff, unsigned long long n)
{                                      
	
	if ( n < 1024 )
		mysnprintf(buff, 7, "%4lluK", n);
	else if ( n < 1024*1024*100 )
		mysnprintf(buff, 7, "%4lluM", n/1024);
	else
		mysnprintf(buff, 7, "%4lluG", n/(1024*1024));
}

static void meminfo_write(char *buff)
{
	FILE *fp;
	char buf[256];
	unsigned long int kb_main_total, kb_main_free, kb_main_available, kb_main_cached, kb_main_buffers;
	unsigned long int SwapTotal, SwapFree;
	int i;

	fp = fopen("/proc/meminfo", "r");
	if ( fp == NULL ) {
		PDEBUG("huj %d: %s ", errno, strerror(errno));
		return;
	}
	fgets(buf, 256, fp);
	sscanf(strchr(buf, ':'), ": %lu", &kb_main_total);
	fgets(buf, 256, fp);
	sscanf(strchr(buf, ':'), ": %lu", &kb_main_free);
        fgets(buf, 256, fp);
#if defined( LEONIDAS )
        sscanf(strchr(buf, ':'), ": %lu", &kb_main_available);
#endif
	fgets(buf, 256, fp);
	sscanf(strchr(buf, ':'), ": %lu", &kb_main_buffers);
	fgets(buf, 256, fp);
	sscanf(strchr(buf, ':'), ": %lu", &kb_main_cached);
	
#if defined( LEONIDAS )
	for(i=0; i<9; i++)
		fgets(buf, 256, fp);
#elif defined( USTROPECET )
	for(i=0; i<12; i++)
		fgets(buf, 256, fp);
#endif

	
	fgets(buf, 256, fp);
	sscanf(strchr(buf, ':'), ": %lu", &SwapTotal);
	fgets(buf, 256, fp);
	sscanf(strchr(buf, ':'), ": %lu", &SwapFree);
	
	fclose(fp);

	//printf("%d %d %d %d \n", SwapTotal, SwapFree, kb_main_total, kb_main_free);

	mysnprintf(buff, 6, "%4dM/", (int)((kb_main_total - kb_main_free - kb_main_cached - kb_main_buffers)/1024) );
	readable_mem_size(buff+6, SwapTotal-SwapFree);
}

static void meminfo_percent(float *ram, float *swap)
{
	FILE *fp;
	char buf[256];
	unsigned long int kb_main_total, kb_main_free, kb_main_available, kb_main_cached, kb_main_buffers;
	unsigned long int SwapTotal, SwapFree;
	int i;

	fp = fopen("/proc/meminfo", "r");
	if ( fp == NULL ) {
		PDEBUG("huj %d: %s ", errno, strerror(errno));
		return;
	}
	fgets(buf, 256, fp);
	sscanf(strchr(buf, ':'), ": %lu", &kb_main_total);
	fgets(buf, 256, fp);
	sscanf(strchr(buf, ':'), ": %lu", &kb_main_free);
        fgets(buf, 256, fp);
#if defined( LEONIDAS )
        sscanf(strchr(buf, ':'), ": %lu", &kb_main_available);
#endif
	fgets(buf, 256, fp);
	sscanf(strchr(buf, ':'), ": %lu", &kb_main_buffers);
	fgets(buf, 256, fp);
	sscanf(strchr(buf, ':'), ": %lu", &kb_main_cached);
	
#if defined( LEONIDAS )
	for(i=0; i<9; i++)
		fgets(buf, 256, fp);
#elif defined( USTROPECET )
	for(i=0; i<12; i++)
		fgets(buf, 256, fp);
#endif

	
	fgets(buf, 256, fp);
	sscanf(strchr(buf, ':'), ": %lu", &SwapTotal);
	fgets(buf, 256, fp);
	sscanf(strchr(buf, ':'), ": %lu", &SwapFree);
	
	fclose(fp);

	//printf("%d %d %d %d \n", SwapTotal, SwapFree, kb_main_total, kb_main_free);

	//mysnprintf(buff, 6, "%4dM/", (int)((kb_main_total - kb_main_free - kb_main_cached - kb_main_buffers)/1024) );
	//readable_mem_size(buff+6, SwapTotal-SwapFree);
	*ram = (float)((kb_main_total - kb_main_free - kb_main_cached - kb_main_buffers)/1024)/(float)(kb_main_total);
	*swap = (float)(SwapTotal-SwapFree)/(float)(SwapTotal);
}

static int how_many_running(char *name)
{
	char buff[256];
	snprintf(buff, 256, "/bin/bash -c \"ps aux|grep \'%s\'|grep -v grep|wc -l\"", name);
	
	FILE *pipe;
	
	pipe = popen(buff, "r");
	
	if (NULL == pipe) {
		perror("pipe");
	}
	
	fgets(buff, sizeof(buff), pipe);
	
	pclose(pipe);
	
	return atoi(buff);
}

static void connect_msgsrv_block()
{
	for(;;) {
		sockfd = msglcd_connect(server_ip);
		if ( sockfd != 0 )
			break;
		PDEBUG("could not connecd to lcs server\n");
		sleep(20);
	}
}

static void handle_msglcd_handle_server(const int lcd_sock) 
{
	int i;
	i = msglcd_handle_server(lcd_sock);
	switch ( i ) {
	case -5:
	case -1:
		PDEBUG("Strange error occured %d ", i);
		break;
	case -4:
		PDEBUG("Server closed the connection. %d ", i);
		break;
	case -6:
		PDEBUG("server sended error messege %d", i);
		break;
	case -2:
		PDEBUG("Server closed the connection without sending exit mesg. %d ", i);
		break;
	case -3:
		PDEBUG("my mesg has somth wrong %d ", i);
		break;
	}
}

static void handle_msg_updat(const int sockfd, const char nr, const char pri, const char *mesg, const int len) 
{
	int i;
	i = msglcd_updat(sockfd, nr, pri, mesg, len);
	if ( i == 0 ) 
		return;
	PDEBUG("could not update mesg. msglcd_updat returned: %d", i);
	connect_msgsrv_block();
	msglcd_updat(sockfd, nr, pri, mesg, len);
}

static void main_for(void)
{
#if defined( LEONIDAS )
	int i;
	char buff[3][41] = { [0 ... 2] = { [0 ... 40] = ' '} };
		/*[0] = "                               up   :   ",
		[1] = "CPU:    %    %    %    %     M/         ",
		[2] = "                                        ", //"    CPU:  C MB:  C CPU:  C CORE:  C     ",
		[3] = "leonidas eth0 in:       out:            ",
		[4] = " %d hostapds, %d dhcpcd wlan0 :D        ",
	};*/
	int g_net_use_size = 0;
	for (;;) {
		
		/* first line, write time */
		/* date | centereed int the first 30 chars */
		const time_t CurentTime = time(NULL);
		int len = 0;
		len += strftime(buff[0], 40, "%2d.%2m.%2y   %2H:%2M:%2S  ", localtime(&CurentTime));
		if ( !len ) 
			fatal("strftime");
		
		/* second line */
		float cpuuse[CPUNUM];
		/* get cpu usage */
		get_cpu_usage(cpuuse);
		len += sprintf(buff[0]+len, " CPU");
		for (i = 0; i < CPUNUM; i++) {
			len += sprintf(buff[0]+len, "%1d", (int)((cpuuse[i]-0.0000001)/10.0));
			//readable_cpu_usage(buff[1]+5*i+5, cpuuse[i]);
		}
		
		float ram = 0.0, swap = 0.0;
		meminfo_percent(&ram, &swap);
		len+=snprintf(buff[0]+len, 41-len, " MEM%1d SWAP%1d ", (int)((ram-0.01)/10.0), (int)((swap-0.01)/10.0));
	
		/* second line */
		len = 0;
		/* GET bandwitch rx and tx speed */
		dynamic_get_net_use(&g_net_use, &g_net_use_size);
		if ( g_net_use_size >= 1 ) {
			char tmp[5], tmp2[5];
			readable_net_size(tmp, g_net_use[0].rx, 4);
			readable_net_size(tmp2, g_net_use[0].tx, 4);
			tmp[4] = tmp2[4] = '\0';
			len += sprintf(buff[1], "NET: %3s^ %3sv  ", tmp, tmp2);
		}
		get_disc_use(disc_use);
		len += snprintf(buff[1]+len, 41-len, " DISC:%6lurd%6luwr    ", 
			disc_use[0].rd_sectors/refresh_time, disc_use[0].wr_sectors/refresh_time);
			
		/* third line, temperatures */
		snprintf(buff[2], 41, "    CPU:%2.0f NB:%2.0f SB:%2.0f CPU:%2.0f GPU:%2.0f     ",
			get_temp(1),get_temp(2),get_temp(3),get_temp(4),get_temp(5));
		
		/* write  when debug, buffers on the screen */
		if ( debug ) {
			int j;
			for (i=0; i < ((sizeof(buff)/sizeof(*buff)/sizeof(**buff))); i++) {
				for (j = 0; j < 40; j++)
					printf("%c", buff[i][j]);
				printf("\n");
			}
			printf("\n");
		}
			
		/* send the message */
		for ( i = 0; i < ((sizeof(buff)/sizeof(*buff)/sizeof(**buff))); i++) {
			handle_msg_updat(sockfd, i, MSG_INFO, buff[i], 40);
			if ( i == 4 )
				handle_msg_updat(sockfd, i, MSG_DEBUG, buff[i], 40);
		}
		
		/* handle server messages */
		handle_msglcd_handle_server(sockfd);
		
		sleep(refresh_time);
	}


#elif defined(FUCK_YOU_IN_THE_ASS)
	{
		/*if ( i == 1 ) {
			mysnprintf(buff[3], 40, "%6s>      <       |      >     <     ", g_net_use[0].name);
			readable_net_size(buff[3]+8, g_net_use[0].rx);
			readable_net_size(buff[3]+15, g_net_use[0].tx);
		} else if ( i >= 2 ) {
			mysnprintf(buff[3], 40, "%6s>      <       |%6s>     <     ", g_net_use[0].name, g_net_use[1].name);
			readable_net_size(buff[3]+8,  g_net_use[0].rx);
			readable_net_size(buff[3]+15, g_net_use[0].tx);
			readable_net_size(buff[3]+29, g_net_use[1].rx);
			readable_net_size(buff[3]+35, g_net_use[1].tx);
		}*/
		
		/* 5 line */
		if ( i >= 2 ) { // there is wlan0 
			snprintf(buff[4], 40, " %2d hostapds, %2d dhcpd wlan0 :D        ",
				how_many_running("hostapd"), how_many_running("dhcpd wlan0") );
		}
				
		/* write  when debug, buffers on the screen */
		if ( debug ) {
			int j;
			for (i=0; i < ((sizeof(buff)/sizeof(*buff)/sizeof(**buff))); i++) {
				for (j = 0; j < 40; j++)
					printf("%c", buff[i][j]);
				printf("\n");
			}
			printf("\n");
		}
			
		/* send the message */
		for ( i = 0; i < ((sizeof(buff)/sizeof(*buff)/sizeof(**buff))); i++) {
			handle_msg_updat(sockfd, i, MSG_INFO, buff[i], 40);
			if ( i == 4 )
				handle_msg_updat(sockfd, i, MSG_DEBUG, buff[i], 40);
		}
		
		/* handle server messages */
		handle_msglcd_handle_server(sockfd);
		
		sleep(refresh_time);
	} /* for(;;) */
	
#elif defined( ROUTER )

	struct net_use_type net_old[4] = { [ 0 ... sizeof(net_old)/sizeof(*net_old)-1 ] = {0,0} };
	char buff[3][41];
	memset(buff, ' ', sizeof(buff));
	buff[0][0] = 'R';
	buff[0][1] = 'O';
	buff[0][2] = 'U';
	buff[0][3] = ' ';
	for (;;) {
		int i;
		
		{ /* uptime */
			/* get sysinfo info */
			struct sysinfo sys_info;
			if ( sysinfo(&sys_info) != 0 )
				fatal("sysinfo");
			int hours = sys_info.uptime / 3600;
			int mins = (sys_info.uptime / 60) - (hours * 60);
			mysnprintf(buff[0]+34, 7, "%3d:%2d", hours, mins);
		}
		
		/* second line */
		{
			float cpuuse[CPUNUM];
			/* get cpu usage */
			get_cpu_usage(cpuuse);
			for (i = 0; i < CPUNUM; i++) {
				readable_cpu_usage(buff[0]+4+4*i, cpuuse[i]);
				buff[0][4+4*i+3] = '%';
			}
		}
		/* write total used ram */
		meminfo_write(buff[0]+20);
		
		/* forth line, write bandwitch speed */
		{
			struct net_use_type net_new[4];
			mysnprintf(buff[1], 39, "ROU0  >      <       |ROU1  >     <     ");
			mysnprintf(buff[2], 39, "ROU2  >      <       |ROU3  >     <     ");
			
			/* GET bandwitch rx and tx speed */
			get_net_use(&net_new[0], "eth0");
			readable_net_size(buff[1]+8,  net_new[0].rx-net_old[0].rx);
			readable_net_size(buff[1]+15, net_new[0].tx-net_old[0].tx);
			net_old[0] = net_new[0];
			
			get_net_use(&net_new[1], "eth2");
			readable_net_size(buff[1]+29, net_new[1].rx-net_old[1].rx);
			readable_net_size(buff[1]+35, net_new[1].tx-net_old[1].tx);
			net_old[1] = net_new[1];
			
			get_net_use(&net_new[2], "eth3");
			readable_net_size(buff[2]+8,  net_new[2].rx-net_old[2].rx);
			readable_net_size(buff[2]+15, net_new[2].tx-net_old[2].tx);
			net_old[2] = net_new[2];
			
			get_net_use(&net_new[3], "eth4");
			readable_net_size(buff[2]+29, net_new[3].rx-net_old[3].rx);
			readable_net_size(buff[2]+35, net_new[3].tx-net_old[3].tx);
			net_old[3] = net_new[3];
	
		}
				
		/* write  when debug, buffers on the screen */
		if ( debug ) {
			int j;
			for (i=0; i < ((sizeof(buff)/sizeof(*buff)/sizeof(**buff))); i++) {
				for (j = 0; j < 40; j++)
					printf("%c", buff[i][j]);
				printf("\n");
			}
			printf("\n");
		}
		
		{ 
			int i;
			/* send the message */
			for ( i = 0; i < ((sizeof(buff)/sizeof(*buff)/sizeof(**buff))); i++) {
				handle_msg_updat(sockfd, i, MSG_INFO, buff[i], 40);
			}
		}
		
		/* handle server messages */
		handle_msglcd_handle_server(sockfd);
		
		sleep(refresh_time);
	} /* for(;;) */
	
#elif defined( USTROPECET )

	struct net_use_type net_old[1];
	char buff[2][41] = {
		"USTR                                    ",
		"USTR  >      <                          " 
	};
	memset(net_old, ' ', sizeof(net_old));
	for (;;) {
		int i;
		float cpuuse[CPUNUM];
		struct sysinfo sys_info;
		struct net_use_type net_new[1];
		
		if (sysinfo(&sys_info) != 0) fatal("sysinfo");
		int days = sys_info.uptime / 3600 / 24;
		int hours = sys_info.uptime / 3600 - (days*24);
		int mins = (sys_info.uptime / 60) - ( (hours+days*24) * 60) ;
		mysnprintf(buff[0]+30, 12, "%3d:%2d:%2d", days, hours, mins);
		
		/* get cpu usage */
		get_cpu_usage(cpuuse);
		for (i = 0; i < CPUNUM; i++) {
			readable_cpu_usage(buff[0]+8+5*i, cpuuse[i]);
			buff[0][4*i+3+8] = '%';
		}
		meminfo_write(buff[0]+19);
					
		/* GET bandwitch rx and tx speed */
		get_net_use(&net_new[0], "eth1");
		readable_net_size(buff[1]+8, net_new[0].rx-net_old[0].rx);
		readable_net_size(buff[1]+15, net_new[0].tx-net_old[0].tx);
		net_old[0] = net_new[0];
		
		snprintf(buff[1]+21, 19, "| %d dvb running   ", how_many_running("dvblast"));
				
		/* write  when debug, buffers on the screen */
		if ( debug ) {
			int j;
			for (i=0; i < ((sizeof(buff)/sizeof(*buff)/sizeof(**buff))); i++) {
				for (j = 0; j < 40; j++)
					printf("%c", buff[i][j]);
				printf("\n");
			}
			printf("\n");
		}
	
		/* send the message */
		for ( i = 0; i < ((sizeof(buff)/sizeof(*buff)/sizeof(**buff))); i++) {
			handle_msg_updat(sockfd, i, MSG_INFO, buff[i], 40);
		}	
		
		/* handle server messages */
		handle_msglcd_handle_server(sockfd);
		
		sleep(refresh_time);
	} /* for(;;) */
	
#else
#error FUCK YOU
#endif

}

int main(int argc, char **argv) 
{
	
	parse_cmd(argc, argv);

	if (!server_ip) {
		fprintf(stderr, "Please give msgsrv ip address.\n");
		exit(0);
	}
	
	signal(SIGHUP,sig_hup);
	signal(SIGQUIT,sig_hup);
	signal(SIGTERM,sig_hup);
	signal(SIGINT,sig_hup);
	on_exit(safe_exit, NULL);
	
#if defined( LEONIDAS )
	printf(" startup ! \n");
#endif
	
	connect_msgsrv_block();

	if ( !debug ) { 
#if defined( LEONIDAS )
		openlog(MY_NAME,LOG_PID,LOG_DAEMON);
		syslog(LOG_INFO,"Startup  succeeded.");
#endif
	}
	
	PDEBUG("Connected with %s.\n", inet_ntoa(*(struct in_addr *)((char *)(struct in_addr *)&server_ip)));
	
	main_for();
	
	return(0);
}

